package fei.typhoon.engine.load;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import fei.typhoon.engine.android.FeiScreen;

public class BitmapLoad {

	/** 加载图片需要的 */
	public FeiScreen screen = null;
	/** 加载图片用的矩阵 */
	private Matrix matrix = null;
	/** 存放图片 */
	private Map<String, FeiBitmap> pool = null;

	public BitmapLoad(FeiScreen screen) {
		this.screen = screen;
		matrix = new Matrix();
		pool = new HashMap<String, FeiBitmap>();
	}

	private FeiBitmap loadBitmap(int id) {
		FeiBitmap feiBitmap = null;
		Bitmap bitmap = null;
		BitmapFactory.Options opts = new BitmapFactory.Options();
		opts.inJustDecodeBounds = true;
		BitmapFactory.decodeResource(screen.getResources(), id, opts);
		opts.inSampleSize = computeSampleSize(opts, -1, opts.outWidth
				* opts.outHeight);
		opts.inJustDecodeBounds = false;
		try {
			Bitmap temp = BitmapFactory.decodeResource(screen.getResources(),
					id, opts);
			if (screen.isBitmapZoomReally() && temp != null) {
				bitmap = resizeBitmap(temp);
				if (bitmap != null && bitmap != temp) {
					temp.recycle();
				}
				temp = null;
			} else {
				bitmap = temp;
			}
		} catch (OutOfMemoryError err) {
			err.printStackTrace();
		}

		if (bitmap != null) {
			feiBitmap = new FeiBitmap(bitmap);
			pool.put("R_" + id, feiBitmap);
		}

		return feiBitmap;
	}

	private FeiBitmap loadBitmap(String name) {
		if (name == null || "".equals(name)) {
			return null;
		}
		FeiBitmap feiBitmap = null;
		Bitmap bitmap = null;

		// 根据图像的名称获取图像的输入流
		InputStream is = null;
		try {
			is = screen.getResources().getAssets().open(name);
		} catch (IOException e) {
			e.printStackTrace();
		}

		if (is != null) {
			try {
				BitmapFactory.Options opts = new BitmapFactory.Options();
				opts.inJustDecodeBounds = true;
				BitmapFactory.decodeStream(is, null, opts);
				opts.inSampleSize = computeSampleSize(opts, -1, opts.outWidth
						* opts.outHeight);
				opts.inJustDecodeBounds = false;

				// 将流绘制成Bitmap图像
				Bitmap temp = BitmapFactory.decodeStream(is, null, opts);
				if (screen.isBitmapZoomReally() && temp != null) {
					bitmap = resizeBitmap(temp);
					if (bitmap != null && bitmap != temp) {
						temp.recycle();
					}
					temp = null;
				} else {
					bitmap = temp;
				}

			} catch (OutOfMemoryError err) {
				// 旋转出现内存溢出
				err.printStackTrace();
			}
		}

		if (bitmap != null) {
			feiBitmap = new FeiBitmap(bitmap);
			pool.put(name, feiBitmap);
		}

		return feiBitmap;
	}

	/**
	 * 图像的自由缩放
	 * 
	 * @param image
	 * @param scaleX
	 *            X方向的缩放比例
	 * @param scaleY
	 *            Y方向的缩放比例
	 * @param flag
	 * @return
	 */
	private Bitmap resizeBitmap(Bitmap bitmap) {
		float scaleX = 1.0f, scaleY = 1.0f;
		if (screen.isKeepProportion()) {
			scaleX = screen.getScale();
			scaleY = screen.getScale();
		} else {
			scaleX = screen.getScaleX();
			scaleY = screen.getScaleY();
		}
		return resizeBitmap(bitmap, scaleX, scaleY, true);
	}
	
	private int computeSampleSize(BitmapFactory.Options options,
			int minSideLength, int maxNumOfPixels) {
		int initialSize = computeInitialSampleSize(options, minSideLength,
				maxNumOfPixels);
		int roundedSize;
		if (initialSize <= 8) {
			roundedSize = 1;
			while (roundedSize < initialSize) {
				roundedSize <<= 1;
			}
		} else {
			roundedSize = (initialSize + 7) / 8 * 8;
		}
		return roundedSize;
	}

	private int computeInitialSampleSize(BitmapFactory.Options options,
			int minSideLength, int maxNumOfPixels) {
		double w = options.outWidth;
		double h = options.outHeight;
		int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
				.sqrt(w * h / maxNumOfPixels));
		int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math
				.floor(w / minSideLength), Math.floor(h / minSideLength));
		if (upperBound < lowerBound) {
			// return the larger one when there is no overlapping zone.
			return lowerBound;
		}
		if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
			return 1;
		} else if (minSideLength == -1) {
			return lowerBound;
		} else {
			return upperBound;
		}
	}

	public Bitmap resizeBitmap(Bitmap bitmap, float scaleX,
			float scaleY, boolean flag) {
		if (bitmap == null) {
			return null;
		}
		// 没有缩放，返回原始图像
		if (scaleX == 1 && scaleY == 1) {
			return bitmap;
		}

		Bitmap resizedBitmap = bitmap;

		// 获取原始图像的大小
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();

		matrix.reset();
		matrix.postScale(scaleX, scaleY);
		try {
			// 重绘图像
			resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height,
					matrix, flag);
		} catch (OutOfMemoryError e) {
			resizedBitmap = bitmap;
			// 缩放出现内存溢出
			e.printStackTrace();
		}

		return resizedBitmap;
	}

	public FeiBitmap getImage(int id) {
		FeiBitmap bitmap = null;
		if (pool.containsKey("R_" + id)) {
			bitmap = pool.get("R_" + id);
			if (bitmap.isRecycled()) {
				bitmap = loadBitmap(id);
			}
		} else {
			bitmap = loadBitmap(id);
		}
		return bitmap;
	}

	public FeiBitmap getImage(String name) {
		FeiBitmap bitmap = null;
		if (pool.containsKey(name)) {
			bitmap = pool.get(name);
			if (bitmap.isRecycled()) {
				bitmap = loadBitmap(name);
			}
		} else {
			bitmap = loadBitmap(name);
		}
		return bitmap;
	}

	public void storeImage(int id, FeiBitmap bitmap) {
		if (bitmap != null) {
			pool.put("R_" + id, bitmap);
		}
	}

	public void storeImage(String name, FeiBitmap bitmap) {
		if (bitmap != null) {
			pool.put(name, bitmap);
		}
	}

	public void disposeImage(int id) {
		if (!pool.containsKey("R_" + id)) {
			FeiBitmap bitmap = pool.get("R_" + id);
			if (bitmap != null) {
				bitmap.recycle();
			}
			pool.remove("R_" + id);
		}
	}

	public void disposeImage(String name) {
		if (!pool.containsKey(name)) {
			FeiBitmap bitmap = pool.get(name);
			if (bitmap != null) {
				bitmap.recycle();
			}
			pool.remove(name);
		}
	}

	public void release() {
		for (Map.Entry<String, FeiBitmap> imgs : pool.entrySet()) {
			FeiBitmap bitmap = imgs.getValue();
			if (bitmap != null && !bitmap.isRecycled()) {
				bitmap.recycle();
			}
		}
		pool.clear();
	}
}
